import edu.vanderbilt.isis.sm.Event;
import edu.vanderbilt.isis.sm.StateflowInterpreter;
import edu.vanderbilt.isis.sm.SymbolicDataProvider;

public class TestVPC {
	TopLevelVPC vpc;

	public TestVPC() {
		this.vpc = new TopLevelVPC();

		this.vpc.sim = new StateflowInterpreter(this.vpc.sm, null);
		this.vpc.sim.disablePrinting();

		this.vpc.initializeTransitions();
		this.vpc.sim.initialize();
	}
	
	/**
	 * Set initial bindings between AnchorCell and VPCs.
	 * Arguments correspond to variables in the Organiser module of NuSMV model.
	 * Should be executed symbolically
	 */
	public void init(int mut_ac_is, int mut_ls_left, int mut_ls_right, int mut_lin12, int mut_let23, 
					int mut_sem5, int mut_let60, int mut_mpk1, int mut_dep1, int mut_lst, boolean go, int time) {
		this.vpc.r1.VPC3.IS = mut_ac_is;
		this.vpc.r1.VPC3.LSleft = mut_ls_left;
		this.vpc.r1.VPC3.LSright = mut_ls_right;
		this.vpc.r1.VPC3.v_lin12 = mut_lin12;
		this.vpc.r1.VPC3.v_let23 = mut_let23;
		this.vpc.r1.VPC3.v_sem5 = mut_sem5;
		this.vpc.r1.VPC3.v_let60 = mut_let60;
		this.vpc.r1.VPC3.v_mpk1 = mut_mpk1;
		this.vpc.r1.VPC3.v_dep1 = mut_dep1;
		this.vpc.r1.VPC3.v_lst = mut_lst;
		this.vpc.r1.VPC3.go = true;
		this.vpc.r1.VPC3.time = 0;
	}

	public void advance(int ac_is, int ls_left, int ls_right, boolean vpc_go, int vpc_time) {
		this.vpc.r1.VPC3.IS = ac_is;
		this.vpc.r1.VPC3.LSleft = ls_left;
		this.vpc.r1.VPC3.LSright = ls_right;
		this.vpc.r1.VPC3.go = vpc_go;
		this.vpc.r1.VPC3.time = vpc_time;
	}

	public void runMachines() {
		// Set initial values. This will be a symbolic method.
	
		printAll("AC and VPCs before executing any transition:");
		
		init(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false ,0);

		Event e = new Event("");

		// Pass the empty event to all components. Execute a first step
		this.vpc.sim.addEvent(e); 
		this.vpc.sim.step();
		
		printAll("After first event has been passed to all components:");
		
		// iterate
		for (int i = 0; i < 4; i++) {
			System.out.println("i = " + i);

			advance(0,0,0,false,0);
			
			this.vpc.sim.addEvent(e); 
			this.vpc.sim.step();
			
			printAll();
		}
	}

	public static void main(String[] args) {
		System.out.println("********************");
		TestVPC bs = new TestVPC();
		bs.runMachines();		
	}
	
	// Printing methods
	public void printAll(){
		printAll("");
	}
	
	public void printAll(String msg){
		System.out.println("------------------ BioSystem");
		System.out.println(msg);
		
		printVPC(this.vpc);

		System.out.println("------------------");
	}

	private static void printVPC(TopLevelVPC vpc) {
		StringBuilder builder = new StringBuilder();
		builder.append("VPC={lst=" + vpc.r1.VPC3.lst);
		builder.append("; LS=" + vpc.r1.VPC3.LS);
		builder.append("; sur2=" + vpc.r1.VPC3.sur2);
		builder.append("; let23=" + vpc.r1.VPC3.let23);
		builder.append("; sem5=" + vpc.r1.VPC3.sem5);
		builder.append("; let60=" + vpc.r1.VPC3.let60);
		builder.append("; mpk1=" + vpc.r1.VPC3.mpk1);
		builder.append("; lin12=" + vpc.r1.VPC3.lin12);
		builder.append("; dep1=" + vpc.r1.VPC3.dep1);
		builder.append("; fate=" + vpc.r1.VPC3.fate);
		builder.append("; cellcycle=" + vpc.r1.VPC3.cellcycle);
		builder.append("; counter=" + vpc.r1.VPC3.counter);
		builder.append("}");
		System.out.println(builder.toString());
	}
}
